home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
t_sys5
/
unixkit.tgz
/
unixkit.tar
/
unixkit
/
thread
/
ksubr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-26
|
8KB
|
307 lines
#include <stdio.h> /***/
/* Machine or compiler-dependent portions of kernel - UNIX version */
#include <signal.h>
#include "global.h"
#include "proc.h"
#ifndef NO_INTSTK
extern int16 Intstk[]; /* The signal stack */
#endif
/* If you don't have one of those machines you'd better look up the
* contents of jmp_buf in setjmp.h or in your manual. If those don't
* give you any hints you will have to write a small program to poke
* around in a jmp_buf in order to find JB_SP
*/
#ifndef JB_SP
#if defined(i386)
/* Template for some of the contents of the jmp_buf array on a Sun386i */
#define JB_ONSSTACK 0
#define JB_SP 2 /* Stack pointer */
#endif
#if defined(sun4) || defined(sparc)
/* Template for some of the contents of the jmp_buf array on a Sun4. */
#define JB_ONSSTACK 0
#define JB_SP 2 /* Stack pointer */
#endif
#if defined(sun3) || defined(mc68020) || defined(mc68000)
/* Template for some of the contents of the jmp_buf array on a Sun3. */
#define JB_ONSSTACK 0
#define JB_SP 2 /* Stack pointer */
#endif
#endif
void
kinit()
{
int i;
/* Initialize interrupt stack for high-water-mark checking */
#ifndef NO_INTSTK
for(i=0;i<INTSTK_SIZE;i++)
Intstk[i] = STACKPAT;
#endif
}
/* ps() will show strange values for the stack usage of the main process.
This is beacuse we do not fill the stack space of the main process
with STACKPAT.
*/
/* Print process table info
* Since things can change while ps is running, the ready proceses are
* displayed last. This is because an interrupt can make a process ready,
* but a ready process won't spontaneously become unready. Therefore a
* process that changes during ps may show up twice, but this is better
* than not having it showing up at all.
*/
int
ps(argc,argv,p)
int argc;
char **argv;
void *p;
{
register struct proc *pp;
int i;
jmp_buf env;
#ifndef NO_INTSTK
struct sigstack oss;
sigstack((struct sigstack *)0,&oss);
tprintf("Int Stack SP stksize maxstk\n");
tprintf(" %-10lx%-10u%-10u\n",
(int)oss.ss_sp,INTSTK_SIZE,chkintstk());
#endif
tprintf("PID SP stksize maxstk event fl in out name\n");
for(pp = Susptab;pp != NULLPROC;pp = pp->next){
if(tprintf("%-10lx%-10lx%-10u%-10u%-10lx%c%c%c %3d %3d %s\n",
ptol(pp),
ptol(pp->env[JB_SP]),
pp->stksize,
stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input, pp->output,
pp->name) == EOF)
return 0;
}
for(i=0;i<PHASH;i++){
for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
if(tprintf("%-10lx%-10lx%-10u%-10u%-10lx%c%c%c %3d %3d %s\n",
ptol(pp),ptol(pp->env[JB_SP]),pp->stksize,stkutil(pp),
ptol(pp->event),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,pp->output,
pp->name) == EOF)
return 0;
}
}
for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
if(tprintf("%-10lx%-10lx%-10u%-10u %c%c%c %3d %3d %s\n",
ptol(pp),ptol(pp->env[JB_SP]),pp->stksize,stkutil(pp),
pp->i_state ? 'I' : ' ',
(pp->state & WAITING) ? 'W' : ' ',
(pp->state & SUSPEND) ? 'S' : ' ',
pp->input,pp->output,
pp->name) == EOF)
return 0;
}
setjmp(env);
if(Curproc != NULLPROC){
tprintf("%-10lx%-10lx%-10u%-10u %c %3d %3d %s\n",
ptol(Curproc),ptol(env[JB_SP]),Curproc->stksize,
stkutil(Curproc),
Curproc->i_state ? 'I' : ' ',
Curproc->input,Curproc->output,
Curproc->name);
}
return 0;
}
int
stkutil(pp)
struct proc *pp;
{
unsigned i;
register int16 *sp;
if (pp->stack == NULL)return 0;
i = pp->stksize;
for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
i--;
return i;
}
/* Return number of used words in interrupt stack. Note hardwired value
* for stack size;
*/
chkintstk()
{
register int i;
register int16 *cp;
#ifndef NO_INTSTK
for(i=INTSTK_SIZE,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)i--;
return i;
#else
return 0;
#endif
}
/* Verify that stack pointer for current process is within legal limits;
* also check that no one has dereferenced a null pointer
*/
void
chkstk()
{
int16 *sbase;
int16 *stop;
int16 *sp;
jmp_buf env;
/* Warning! KA9WSB
* Some systems don't reliably tell you that they are on the signal stack.
* Comment out this routine if that's the case. It should probably be
* replaced anyway...
*/
if(Curproc == NULLPROC)return;
setjmp (env);
sp = (int16 *) env[JB_SP];
#ifdef JB_ONSSTACK
if(env[JB_ONSSTACK]){
/* Probably in interrupt context */
return;
}
#endif
sbase = Curproc->stack;
if (sbase == 0)
return;
stop = sbase + Curproc->stksize;
if(sp < sbase || sp >= stop){
printf("Stack violation, process %s\n",Curproc->name);
printf("SP = %lx, legal stack range [%lx,%lx)\n",
ptol(sp),ptol(sbase),ptol(stop));
fflush(stdout);
abort();
}
}
/* Machine-dependent initialization of a task */
/* Each process gets a stack below the real stack in the stack area.
This is really risky business since the kernel thinks that this area
is unused. Be aware of that this might lead to problems. But it is
unfortunately the only way to make this program work at the moment,
since we are not allowed to move the stack pointer below the heap.
*/
void
psetup(pp,iarg,parg1,parg2,pc)
struct proc *pp; /* Pointer to task structure */
int iarg; /* Generic integer arg */
void *parg1; /* Generic pointer arg #1 */
void *parg2; /* Generic pointer arg #2 */
void (*pc)(); /* Initial execution address */
{
int i, p;
void startproc();
/* Task initially runs with interrupts on */
pp->i_state = 1;
/* The main process needs special treatment. The NULL
initial execution address indicates that this is indeed
the main process. */
if (pc == NULLVFP) {
pp->stksize = 0;
pp->stack = NULL;
return;
}
/* Since the process has its stack in high memory we are not able
* write in it directly. So instead of pushing the a stack frame
* on the stack, we save the frame for later usage by startproc().
*/
pp->startargs.parg2 = parg2;
pp->startargs.parg1 = parg1;
pp->startargs.iarg = iarg;
pp->startargs.func = pc;
/***** HACK we free the stack allocated by kernel.c and get us a new one
* that is probably larger and better aligned :-)
* When we allocate the stack, we have to leave some room at the
* top, because the setjmp function return will presume that it
* has a stack frame in which to scribble... so reserve about
* 256 bytes (64 ints) for the stack... While we're at it, we
* might as well guarantee proper stack alignment. Align it on
* a double-word boundary, which should be the worst case for
* most known processors.
*
* What's in the stack frame is important for some processors
* (notably the SPARC!). So, before we do the assignment of
* the new stack pointer, we copy the previous stack frame over.
* With some assembly we can find the size of the stack frame,
* but it's easier just to copy the entire 256 bytes. NOTE:
* IF YOU ADD A LOT OF STUFF TO THIS ROUTINE, THE FRAME MAY
* GROW BEYOND THE LIMIT!
*
* Note that this will disturb dbx or anything else that tries
* to walk stacks backwards. It may find a partial stack frame
* and crash...
*
*******/
free(pp->stack);
pp->stksize = PROCSTK_SIZE; /* in small ints */
pp->stack = (int16 *)malloc(pp->stksize * sizeof(int16));
for(i=0; i<pp->stksize; i++) pp->stack[i] = STACKPAT;
i = setjmp(pp->env);
if(i){
startproc();
} else {
/* Compute the new stack top */
p = (int)pp->stack;
p = p + (pp->stksize * sizeof(int16)); /* top of stack */
p = p - 256; /* fake current stack frame */
p = (p & 0xfffffff8); /* fix alignment */
/* Copy the frame (or most of it, anyway) */
memcpy((char *)p, (char *)(pp->env[JB_SP]), 256);
/* And set the new stack pointer. */
pp->env[JB_SP] = p;
}
}
/* The process is born and killed here */
void
startproc()
{
(*Curproc->startargs.func)(Curproc->startargs.iarg,
Curproc->startargs.parg1,
Curproc->startargs.parg2);
killself();
}
unsigned
phash(event)
void *event;
{
register unsigned x;
x = (unsigned) event;
/* If PHASH is a power of two, this will simply mask off the
* higher order bits
*/
return x % PHASH;
}